package sg.edu.nus.iss.billing.datastore.tool;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import sg.edu.nus.iss.billing.datastore.DBFactory;
import sg.edu.nus.iss.billing.entity.BaseEntity;
import sg.edu.nus.iss.billing.exception.DataStoreException;

/**
 * A help tool for view data stored in data files
 * This viewer is base on the toString() methods
 * @author Wang Dayong
 *
 */
public class DataStoreViewer extends javax.swing.JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1136085141460984985L;

	private JSplitPane jSplitPane;

	private JScrollPane dataContentPanel;

	private JPanel jPanel1;

	private JList classNameList;

	private JButton searchBtn;

	private JScrollPane jScrollPane1;

	private JTextArea dataContentTextArea;

	private JButton firtBtn;

	private JButton lastBtn;

	private JButton nextBtn;

	private JButton preBtn;

	private JTextField contidionTxt;

	private JPanel upPannel;

	private JPanel jPanel2;

	private String currentClass = "";

	private JLabel infoLbe;

	private int currentPG = 0;

	private int totalCount = 0;

	private int totalPG = 0;

	private static int PAGE_SIZE = 40;
	
	private static final String REFRESH = "Class Name:[Refresh]\t\t\t\t";

	/**
	* Auto-generated main method to display this JFrame
	*/
	public static void main(String[] args) {

		SwingUtilities.invokeLater(new Runnable() {

			public void run() {

				DataStoreViewer inst = new DataStoreViewer();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
				
			}
		});
	}

	public DataStoreViewer() {

		super("DataStore Viewer");
		initGUI();
	}

	private void initGUI() {

		try {
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			{
				jSplitPane = new JSplitPane();
				getContentPane().add(getJSplitPane(), BorderLayout.CENTER);
				{
					dataContentPanel = new JScrollPane();
					jSplitPane.add(getDataContentPanel(), JSplitPane.RIGHT);
					dataContentPanel.setViewportView(getJPanel2());
				}
				{
					jPanel1 = new JPanel();
					FlowLayout jPanel1Layout = new FlowLayout();
					jSplitPane.add(jPanel1, JSplitPane.LEFT);
					jPanel1.setLayout(jPanel1Layout);
					{
						ListModel classNameListModel = new DefaultComboBoxModel(loadFileName().toArray(new String[0]));
						classNameList = new JList();
						jPanel1.add(getClassNameList());
						classNameList.setModel(classNameListModel);
						classNameList.addMouseListener(new MouseAdapter() {

							public void mouseClicked(MouseEvent evt) {

								classNameListMouseClicked(evt);
							}
						});
					}
				}
			}
			pack();
			this.setSize(Toolkit.getDefaultToolkit().getScreenSize());   
			this.setLocation(0,20);   
		} catch (Exception e) {
			// add your error handling code here
			e.printStackTrace();
		}
	}

	public JSplitPane getJSplitPane() {

		return jSplitPane;
	}

	public JScrollPane getDataContentPanel() {

		return dataContentPanel;
	}

	public JList getClassNameList() {

		return classNameList;
	}

	public List<String> loadFileName() {

		String storeFolder = "";
		try {
			storeFolder = (new File(".").getCanonicalPath().concat("/data/"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		File file = new File(storeFolder);
		File fs[] = file.listFiles();
		List<String> list = new ArrayList<String>();
		list.add(REFRESH);
		for (File f : fs) {
			String name = f.getName();
			// skip svn file
			if (!name.startsWith("."))
				list.add(name);
		}
		return list;
	}

	
	@SuppressWarnings("unchecked")
	public void loadDataByName(String clazzName, String id) {

		try {
			Class objType = Class.forName(clazzName);
			try {
				List objs = null;
				if (id!=null) {

					Object obj = DBFactory.instance().getSDStore().loadObjectByID(objType, id);
					objs = new ArrayList();
					if (obj!=null) {
						objs.add(obj);
					}
				} else {
					objs = DBFactory.instance().getSDStore().loadObjectsByType(objType);
				}

				totalCount = objs.size();
				if (totalCount==0)
					return;

				totalPG = totalCount/PAGE_SIZE;
				if (totalCount%PAGE_SIZE!=0)
					totalPG += 1;

				StringBuffer sb = new StringBuffer();
				infoLbe.setText("Page:"+(currentPG+1)+" Total Page:"+totalPG+" Total Count:"+totalCount+"\n");
				infoLbe.setVisible(true);
				// sb.append("Page:"+(currentPG+1)+" Total Page:"+totalPG+" Total Count:"+totalCount+"\n");

				int beginIdx = getCurrentBeginIdx();
				for (int i = 0; i<PAGE_SIZE; i++) {
					try {
						BaseEntity obj = (BaseEntity) objs.get(i+beginIdx);
						sb.append("ID:"+obj.getId()+" ");
						sb.append(obj.toString()+"\r\n");
					} catch (IndexOutOfBoundsException ex) {
						break;
					} catch (Exception ex) {
						sb.append(objs.get(i+beginIdx).toString()+"\r\n");
					}
				}

				dataContentTextArea.setText(sb.toString());
			} catch (DataStoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private int getCurrentBeginIdx() {

		return this.currentPG*PAGE_SIZE;
	}

	private void classNameListMouseClicked(MouseEvent evt) {

		JList list = (JList) (evt.getComponent());
		this.currentClass = (String) list.getSelectedValue();
		if(currentClass.equals(REFRESH)){
			// refresh list
			ListModel classNameListModel = new DefaultComboBoxModel(loadFileName().toArray(new String[0]));
			classNameList.setModel(classNameListModel);
			return;
		}
		loadDataByName(currentClass, null);

		
	}

	private JPanel getJPanel2() {

		if (jPanel2==null) {
			jPanel2 = new JPanel();
			BorderLayout jPanel2Layout = new BorderLayout();
			jPanel2.setLayout(jPanel2Layout);
			jPanel2.add(getUpPannel(), BorderLayout.NORTH);
			jPanel2.add(getJScrollPane1(), BorderLayout.CENTER);
		}
		return jPanel2;
	}

	private JPanel getUpPannel() {

		if (upPannel==null) {
			upPannel = new JPanel();
			FlowLayout upPannelLayout = new FlowLayout();
			upPannelLayout.setAlignment(FlowLayout.LEFT);
			upPannel.setLayout(upPannelLayout);
			upPannel.setPreferredSize(new java.awt.Dimension(370, 30));
			upPannel.add(getContidionTxt());
			upPannel.add(getSearchBtn());
			upPannel.add(getFirtBtn());
			upPannel.add(getPreBtn());
			upPannel.add(getNextBtn());
			upPannel.add(getLastBtn());
			upPannel.add(getInfoLbe());
		}
		return upPannel;
	}

	private JScrollPane getJScrollPane1() {

		if (jScrollPane1==null) {
			jScrollPane1 = new JScrollPane();
			jScrollPane1.setViewportView(getDataContentTextArea());
		}
		return jScrollPane1;
	}

	private JTextArea getDataContentTextArea() {

		if (dataContentTextArea==null) {
			dataContentTextArea = new JTextArea();
		}
		return dataContentTextArea;
	}

	private JTextField getContidionTxt() {

		if (contidionTxt==null) {
			contidionTxt = new JTextField();
			contidionTxt.setPreferredSize(new java.awt.Dimension(104, 21));
		}
		return contidionTxt;
	}

	private JButton getFirtBtn() {

		if (firtBtn==null) {
			firtBtn = new JButton();
			firtBtn.setText("<<");
			firtBtn.addMouseListener(new MouseAdapter() {

				public void mouseClicked(MouseEvent evt) {

					firtBtnMouseClicked(evt);
				}
			});
		}
		return firtBtn;
	}

	private JButton getPreBtn() {

		if (preBtn==null) {
			preBtn = new JButton();
			preBtn.setText("<");
			preBtn.addMouseListener(new MouseAdapter() {

				public void mouseClicked(MouseEvent evt) {

					preBtnMouseClicked(evt);
				}
			});
		}
		return preBtn;
	}

	private JButton getNextBtn() {

		if (nextBtn==null) {
			nextBtn = new JButton();
			nextBtn.setText(">");
			nextBtn.addMouseListener(new MouseAdapter() {

				public void mouseClicked(MouseEvent evt) {

					nextBtnMouseClicked(evt);
				}
			});
		}
		return nextBtn;
	}

	private JButton getLastBtn() {

		if (lastBtn==null) {
			lastBtn = new JButton();
			lastBtn.setText(">>");
			lastBtn.addMouseListener(new MouseAdapter() {

				public void mouseClicked(MouseEvent evt) {

					lastBtnMouseClicked(evt);
				}
			});
		}
		return lastBtn;
	}

	private JButton getSearchBtn() {

		if (searchBtn==null) {
			searchBtn = new JButton();
			searchBtn.setText("Search by ID");
			searchBtn.addMouseListener(new MouseAdapter() {

				public void mouseClicked(MouseEvent evt) {

					searchBtnMouseClicked(evt);
				}
			});
		}
		return searchBtn;
	}

	private JLabel getInfoLbe() {

		if (infoLbe==null) {
			infoLbe = new JLabel();
			infoLbe.setPreferredSize(new java.awt.Dimension(376, 16));

		}
		return infoLbe;
	}

	private void searchBtnMouseClicked(MouseEvent evt) {

		String id = this.contidionTxt.getText().trim();
		loadDataByName(currentClass, id);
	}

	private void firtBtnMouseClicked(MouseEvent evt) {

		this.currentPG = 0;
		loadDataByName(currentClass, null);
	}

	private void preBtnMouseClicked(MouseEvent evt) {

		if (currentPG==0)
			return;
		this.currentPG--;
		loadDataByName(currentClass, null);
	}

	private void nextBtnMouseClicked(MouseEvent evt) {

		if (currentPG==totalPG-1)
			return;
		this.currentPG++;
		loadDataByName(currentClass, null);
	}

	private void lastBtnMouseClicked(MouseEvent evt) {

		this.currentPG = totalPG-1;
		loadDataByName(currentClass, null);
	}

}
